﻿using System;
using System.Collections.Generic;

namespace Model
{
    /// <summary>
    /// 全局组件池,用于调度新的空Component、循环使用销毁的Component
    /// 【实体也被作为一个特殊Component存在】
    /// </summary>
    public class ObjectPool
    {
        //Type<->component队列 字典【保存同一类型下所有的空/废弃Component】
        private readonly Dictionary<Type, Queue<Component>> componentDic = new Dictionary<Type, Queue<Component>>();
        /// <summary>
        /// 获取指定类型的新组件
        /// </summary>
        /// <param name="type">组件类型</param>
        /// <returns>空组件</returns>
        public Component Fetch(Type type)
        {
            Queue<Component> queue;
            Component obj;
            //组件队列里面是否有该类型的现成的废弃/空组件
            if(!this.componentDic.TryGetValue(type,out queue))
            {
                //没有那就对这个类型初始化一个新的队列，并添加一个这个类型的空组件
                queue = new Queue<Component>();
                this.componentDic.Add(type, queue);
            }
            //如果获取的组件数量大于0
            if (queue.Count > 0)
            {
                //从队列中取出首部的空组件
                obj = queue.Dequeue();
            }
            else
            {
                //说明没有空组件了，此时直接初始化新的组件实例
                obj = Activator.CreateInstance(type) as Component;
            }
            //标识当前组件是由组件池创建的【同时赋予一个GID】
            obj.IsFromPool = true;
            return obj;
        }
        /// <summary>
        /// 获取指定类型的新组件
        /// </summary>
        /// <param name="T">组件类型</param>
        /// <returns>空组件</returns>
        public T Fetch<T>()
            where T : Component
        {
            T t = (T)this.Fetch(typeof(T));
            return t;
        }
        /// <summary>
        /// 组件再循环
        /// </summary>
        /// <param name="obj">销毁组件</param>
        public void Recycle(Component obj)
        {
            //获取组件类型
            Type type = obj.GetType();
            Queue<Component> queue;
            //将组件加入再循环字典中【没有这个类型的那就新建这个类型的队列】
            if (!this.componentDic.TryGetValue(type, out queue))
            {
                queue = new Queue<Component>();
                this.componentDic.Add(type, queue);
            }
            queue.Enqueue(obj);
        }
    }
}
